package baoyunfs.deviceid;

import android.content.Context;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ExecutorService;

/**
 * 1. 从 SharedPreferences 获取 DID，如果失败，则：
 * 2. 从 System Data 获取 DID，如果失败，则：
 * 3. 从 SD 卡获取 DID，如果失败，则：
 * 4. 使用 AndroidID 作为 DID，如果失败，则
 * 5. 先进行Log上报，然后使用 uuid 作为 DID。
 * 6. 更新DID
 */
public class DeviceIdManager {

    private static final String TAG = "AppX";

    private volatile static DeviceIdManager instance;

    public static DeviceIdManager getInstance() {
        if (instance == null) {
            synchronized (DeviceIdManager.class) {
                if (instance == null) {
                    instance = new DeviceIdManager();
                }
            }
        }
        return instance;
    }

    private String deviceId;
    private OnDeviceIdManagerListener mOnDeviceIdManagerListener;
    private ExecutorService executor;
    private boolean sdCardUseable;

    private DeviceIdManager() {
    }

    public String getDeviceId(){
        return deviceId;
    }

    public String getDeviceId(final Context context) {
        Log.d(TAG, "getDeviceId() called with: context = [" + context + "]");
        if (deviceId == null) {
            deviceId = getDidInner(context);
        }
        return deviceId;
    }

    public void getDeviceId(final Context context, final OnDeviceIdCallBack onDeviceIdCallBack) {
        if (onDeviceIdCallBack == null) return;
        if (deviceId == null) {
            if (executor != null) {
                executor.execute(new Runnable() {
                    @Override public void run() {
                        deviceId = getDidInner(context);
                        onDeviceIdCallBack.callBackDeviceId(deviceId);
                    }
                });
            } else {
                deviceId = getDidInner(context);
                onDeviceIdCallBack.callBackDeviceId(deviceId);
            }
        } else {
            onDeviceIdCallBack.callBackDeviceId(deviceId);
        }
    }

    private String getDidInner(final Context context) {
        String did = UUDidStore.loadDid(context, sdCardUseable);
        if (TextUtils.isEmpty(did)) {
            did = getAndroidID(context);
            if (!TextUtils.isEmpty(did)) {
                if (mOnDeviceIdManagerListener != null) {
                    mOnDeviceIdManagerListener.successOfGetAndroidID();
                }
            }
        }
        if (TextUtils.isEmpty(did)) {
            if (mOnDeviceIdManagerListener != null) {
                mOnDeviceIdManagerListener.failureOfGetAndroidID();
            }
            did = generateUUID();
        }

        Log.d(TAG, "getDidInner() called with: did = [" + did + "]");
        UUDidStore.saveDid(context, did, sdCardUseable);
        return did;
    }

    private String getAndroidID(Context context) {
        String deviceID =
            Settings.System.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
        return deviceID;
    }

    private String generateUUID() {
        UUID uuid = UUID.randomUUID();
        if (null != uuid) {
            return uuid.toString();
        } else {
            return "unknow-" + new Random().nextInt();
        }
    }

    public void setmOnDeviceIdManagerListener(OnDeviceIdManagerListener onDeviceIdManagerListener) {
        if (onDeviceIdManagerListener == null) return;
        this.mOnDeviceIdManagerListener = onDeviceIdManagerListener;
        sdCardUseable = mOnDeviceIdManagerListener.sdCardUseable();
        executor = mOnDeviceIdManagerListener.getExecutorService();
    }

    public interface OnDeviceIdManagerListener {
        boolean sdCardUseable();

        ExecutorService getExecutorService();

        void failureOfGetAndroidID();

        void successOfGetAndroidID();
    }

    public interface OnDeviceIdCallBack {
        void callBackDeviceId(String deviceId);
    }
}
